﻿using System;
using System.Collections.Generic;
using System.Xml;
using System.IO;
using System.Net;

/*
 * Can KAYA
 * cankaya07@gmail.com
 * http://cankaya.net.tr
 */

namespace YahooWeather
{

    public class DayWeather
    {
        #region DayWeather
        public string WeatherText { get; set; }
        public string WeatherCode { get; set; }
        public decimal CurrentTemperature { get; set; }
        public decimal LowTemperature { get; set; }
        public decimal HighTemperature { get; set; }
        public DateTime ForecastDate { get; set; }
        public string DayName { get; set; }
        #endregion
    }

    public class YahooWeather
    {
        #region Properties
        #region Wind
        decimal WindChill { get; set; } //hissedilen sıcaklık
        decimal WindDirection { get; set; } //Degree
        decimal WindSpeed { get; set; } //km/h

        public string strWindChill { get; set; }
        public string strWindDirection { get; set; }
        public string strWindSpeed { get; set; }
        #endregion

        public string Country { get; set; }
        public string City { get; set; }

        #region Atmosphere
        decimal AtmosphereHumidity { get; set; } //percent
        decimal AtmosphereVisibility { get; set; } //km
        decimal AtmospherePressure { get; set; } //mb

        public string strAtmosphereHumidity { get; set; }
        public string strAtmosphereVisibility { get; set; }
        public string strAtmospherePressure { get; set; }
        #endregion

        public DateTime SunRiseTime { get; set; }   //GMT+2
        public DateTime SunSetTime { get; set; }    //GMT+2
        public DateTime LastBuildDate { get; set; } //GMT+2
        public string Language { get; set; }

        #region Units
        string TemperatureUnit { get; set; }
        string DistanceUnit { get; set; }
        string PressureUnit { get; set; }
        string SpeedUnit { get; set; }
        #endregion

        #endregion

        public IList<DayWeather> IDayForecast = new List<DayWeather>();
        public void Getweather(string CityNumber)
        {
            XmlDocument xDoc = LoadWeatherXml(CityNumber);
            ExtractWeatherConditions(xDoc);
            ExtractData(xDoc);
            SetVariableUnits();
        }
        void ExtractWeatherConditions(XmlDocument xDoc)
        {
            XmlNode x = xDoc.SelectSingleNode(@"//rss//channel//item");
            XmlNodeList xNodeList = x.ChildNodes;

            foreach (XmlNode txt in xNodeList)
            {
                if (txt.Name == "yweather:condition" || txt.Name == "yweather:forecast")
                {
                    SetForeCast(txt);
                }
            }
        }        
        XmlDocument LoadWeatherXml(string CityNumber)
        {
            string rssURL = "http://weather.yahooapis.com/forecastrss?w=" + CityNumber + "&u=c";
            WebRequest myRequest = System.Net.WebRequest.Create(rssURL);
            WebResponse myResponse = myRequest.GetResponse();
            using (Stream rssStream = myResponse.GetResponseStream())
            {
                XmlDocument xDoc = new XmlDocument();
                xDoc.Load(rssStream);
                return RemoveSomeUnNecessaryElement(xDoc);
            }
        }
        XmlDocument RemoveSomeUnNecessaryElement(XmlDocument xDoc)
        {

            //XmlNode xn = xDoc.SelectSingleNode(@"//rss//channel//image");
            //xn.ParentNode.RemoveChild(xn);
            //xn = xDoc.SelectSingleNode(@"//rss//channel//link");
            //xn.ParentNode.RemoveChild(xn);
            return xDoc;
        }
        void SetLocation(XmlNode xmlNode)
        {
            City = xmlNode.Attributes["city"].Value;
            Country = xmlNode.Attributes["country"].Value;
        }
        void SetWind(XmlNode xmlNode)
        {
            WindChill = Convert.ToDecimal(xmlNode.Attributes["chill"].Value);
            WindDirection = Convert.ToDecimal(xmlNode.Attributes["direction"].Value);
            WindSpeed = Convert.ToDecimal(xmlNode.Attributes["speed"].Value);
        }
        void SetAtmosphere(XmlNode xmlNode)
        {
            AtmosphereHumidity = Convert.ToDecimal(xmlNode.Attributes["humidity"].Value);
            AtmosphereVisibility = Convert.ToDecimal(xmlNode.Attributes["visibility"].Value);
            AtmospherePressure = Convert.ToDecimal(xmlNode.Attributes["pressure"].Value);
        }
        void SunTimes(XmlNode xmlNode)
        {
            SunRiseTime = Convert.ToDateTime(xmlNode.Attributes["sunrise"].Value);
            SunSetTime = Convert.ToDateTime(xmlNode.Attributes["sunset"].Value);
        }
        void SetUnits(XmlNode xmlNode)
        {
            TemperatureUnit = xmlNode.Attributes["temperature"].Value;
            DistanceUnit = xmlNode.Attributes["distance"].Value;
            PressureUnit = xmlNode.Attributes["pressure"].Value;
            SpeedUnit = xmlNode.Attributes["speed"].Value;
        }
        void SetForeCast(XmlNode xmlNode)
        {
            DayWeather day = new DayWeather();
            if (xmlNode.Attributes["temp"] != null)
            {
                //today
                day.CurrentTemperature = Convert.ToDecimal(xmlNode.Attributes["temp"].Value);
            }
            else
            {
                //tomorrow or 2 days later
                day.LowTemperature = Convert.ToDecimal(xmlNode.Attributes["low"].Value);
                day.HighTemperature = Convert.ToDecimal(xmlNode.Attributes["high"].Value);
            }
            day.WeatherText = xmlNode.Attributes["text"].Value;
            day.ForecastDate = ReFormatDate(xmlNode.Attributes["date"].Value);
            day.WeatherCode = xmlNode.Attributes["code"].Value;
            IDayForecast.Add(day);
        }
        XmlDocument GenerateXmlForSomeExtraInfo(XmlDocument xDoc)
        {
            XmlNode xn = xDoc.SelectSingleNode(@"//rss//channel//item");
            xn.ParentNode.RemoveChild(xn);
            return xDoc;
        }
        void ExtractData(XmlDocument xDoc)
        {
            xDoc = GenerateXmlForSomeExtraInfo(xDoc);
            XmlNode x = xDoc.SelectSingleNode(@"//rss//channel");
            XmlNodeList xNodeList = x.ChildNodes;

            foreach (XmlNode txt in xNodeList)
            {
                switch (txt.Name)
                {
                    case "language":
                        Language = txt.InnerText;
                        break;
                    case "lastBuildDate":
                        LastBuildDate = ReFormatDate(txt.InnerText);
                        break;
                    case "yweather:location":
                        SetLocation(txt);
                        break;
                    case "yweather:units":
                        SetUnits(txt);
                        break;
                    case "yweather:wind":
                        SetWind(txt);
                        break;
                    case "yweather:atmosphere":
                        SetAtmosphere(txt);
                        break;
                    case "yweather:astronomy":
                        SunTimes(txt);
                        break;
                }
            }

        }
        DateTime ReFormatDate(string date)
        {
            //Tue, 29 Jan 2013 1:48 pm EET
            if (date.Contains("EET"))
                return Convert.ToDateTime((date.Split(',')[1]).Replace("EET", ""));
            else
                return Convert.ToDateTime(date);
        }
        void SetVariableUnits()
        {
            strWindChill = WindChill + " " + TemperatureUnit;
            strWindDirection = WindDirection + " " + "Degree";
            strWindSpeed = WindSpeed + " " + SpeedUnit;

            strAtmosphereHumidity = AtmosphereHumidity + " " + "%";
            strAtmospherePressure = AtmospherePressure + " " + PressureUnit;
            strAtmosphereVisibility = AtmosphereVisibility + " " + DistanceUnit;
        }
    }
}

/*
            //     <asp:ListItem Value="2344116" Text="Istanbul"></asp:ListItem>
            //     <asp:ListItem Value="2343732" Text="Ankara"></asp:ListItem>
            //     <asp:ListItem Value="2343733" Text="Antalya"></asp:ListItem>
            //     <asp:ListItem Value="2343859" Text="Çanakkale"></asp:ListItem>
            //     <asp:ListItem Value="2343977" Text="Erzurum"></asp:ListItem>
            //     <asp:ListItem Value="2344117" Text="Izmir"></asp:ListItem>
*/